package com.example.demo.drools.executor;

import com.example.demo.drools.base.RuleException;
import com.example.demo.drools.base.CheckResult;
import com.example.demo.drools.base.RuleFact;
import com.example.demo.drools.base.RuleSchema;
import com.example.demo.drools.util.KieUtil;
import org.drools.core.base.RuleNameStartsWithAgendaFilter;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * 执行器基类
 */
public abstract class AbstractExecutor implements RuleExecutor {
	
	private static Logger LOG = LoggerFactory.getLogger(AbstractExecutor.class);
	
	private static final String SEPARATOR = "_";


	@Override
	public final CheckResult excute(RuleSchema ruleSchema, RuleFact fact) {
		String ruleDrl = ruleSchema.getRuleDrl();
		Assert.hasText(ruleDrl, "规则不能为空");
		Assert.notNull(fact, "规则事实不能为空");
		
		if(!support(fact)) {
			throw new RuleException("不支持的规则执行器");
		}
		LOG.info("创建规则会话:fact = {}", fact);
		long time1 = System.currentTimeMillis();
		KieContainer kContainer = KieUtil.getSchemaRuleContainer(ruleSchema.getSchemaCode(), ruleDrl);
		KieSession kSession = kContainer.newKieSession();
		long time2 = System.currentTimeMillis();
		LOG.info("会话创建成功, 耗时: {}", time2 - time1);
		//默认匹配不成功
		CheckResult result = CheckResult.fail();
		try {
			kSession.setGlobal("log", LOG);
			kSession.setGlobal("result", result);
			insertFact(fact, kSession);
			int count = kSession.fireAllRules(new RuleNameStartsWithAgendaFilter(ruleSchema.getSchemaCode() + SEPARATOR));
			long time3 = System.currentTimeMillis();
			LOG.info("执行成功, 耗时{}毫秒", time3 - time2);
			LOG.info("执行了{}条规则", count);
		} finally {
			if(kSession != null) {
				kSession.dispose();
				kSession.destroy();
			}
		}
		return result;
	}

	
	/**
	 * 如有需要, 可对该方法进行重写
	 * @param fact
	 * @param kSession
	 */
	protected void insertFact(RuleFact fact, KieSession kSession) {
		kSession.insert(fact);
	}

	
}
